﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;


namespace PPC_emulator
{
    public class ByteSwap
    {
        public static UInt16 Swap(UInt16 input)
        {
            if (BitConverter.IsLittleEndian)
                return ((UInt16)(
                    ((0xFF00 & input) >> 8) |
                    ((0x00FF & input) << 8)));
            else
                return input;
        }

        public static UInt32 Swap(UInt32 input)
        {
            if (BitConverter.IsLittleEndian)
                return ((UInt32)(
                    ((0xFF000000 & input) >> 24) |
                    ((0x00FF0000 & input) >> 8) |
                    ((0x0000FF00 & input) << 8) |
                    ((0x000000FF & input) << 24)));
            else
                return input;
        }

        public static UInt64 Swap(UInt64 input)
        {
            if (BitConverter.IsLittleEndian)
                return ((UInt64)(
                    ((0xFF00000000000000 & input) >> 56) |
                    ((0x00FF000000000000 & input) >> 40) |
                    ((0x0000FF0000000000 & input) >> 24) |
                    ((0x000000FF00000000 & input) >> 8) |
                    ((0x00000000FF000000 & input) << 8) |
                    ((0x0000000000FF0000 & input) << 24) |
                    ((0x000000000000FF00 & input) << 40) |
                    ((0x00000000000000FF & input) << 56)));
            else
                return input;
        }
    }

    public static class GlobalFunctions
    {
        public static String fixString(String input,int length)
        {
            String parse = input;
            if (parse.Length > length)
                parse =
                    parse.Substring(parse.Length - length, length);

            while (parse.Length < length)
                parse = "0" + parse;

            return parse;
        }

        public static String shortHex(UInt32 value)
        {
            return Convert.ToString(value, 16).ToUpper();
        }
        
        public static String toHex(UInt32 value,int length)
        {
            return fixString(Convert.ToString(value, 16).ToUpper(), length);
        }

        public static String toHex(long value, int length)
        {
            return toHex((UInt32)value);
        }

        public static String toHex(UInt32 value)
        {
            return toHex(value, 8);
        }

        public static String toHex(long value)
        {
            return toHex((UInt32)value, 8);
        }

        public static bool tryToHex(String input, out UInt32 value)
        {
            value = 0;
            try
            {
                UInt32 temp = Convert.ToUInt32(input, 16);
                value = temp;
                return true;
            }
            catch { }
            return false;
        }

        public static Single UIntToSingle(UInt32 input)
        {
            Byte[] data = BitConverter.GetBytes(input);
            Single result;
            result = BitConverter.ToSingle(data, 0);
            return result;
        }

        public static UInt32 ReadStream(Stream input, int blength)
        {
            Byte[] buffer = new Byte[blength];
            UInt32 result;

            input.Read(buffer, 0, blength);

            switch (blength)
            {
                case 1: result = (UInt32)buffer[0]; break;
                case 2: result = (UInt32)ByteSwap.Swap((UInt16)BitConverter.ToUInt16(buffer, 0)); break;
                default: result = (UInt32)ByteSwap.Swap(BitConverter.ToUInt32(buffer, 0)); break;
            }

            return result;
        }

        public static UInt32 ReadStream(Stream input)
        {
            return ReadStream(input, 4);
        }

        public static void WriteStream(Stream output, UInt32 value, int blength)
        {
            Byte[] buffer = new Byte[blength];
            
            Byte[] vBuffer = vBuffer = BitConverter.GetBytes(value);
           
            switch (blength)
            {
                case 1:
                    buffer[0] = vBuffer[0];
                    break;
                case 2:
                    buffer[0] = vBuffer[1];
                    buffer[1] = vBuffer[0];
                    break;
                default:
                    buffer[0] = vBuffer[3];
                    buffer[1] = vBuffer[2];
                    buffer[2] = vBuffer[1];
                    buffer[3] = vBuffer[0];
                    break;
            }

            output.Write(buffer, 0, blength);

        }

        public static void WriteStream(Stream output, UInt32 value)
        {
            WriteStream(output, value, 4);
        }
    }
}
